## 介绍
- 为对象添加新功能
- 不改变其原有的结构和功能


## 代码演示
```js 

class Circle{
    draw(){
        console.log('画一个圆形');
    }
}


class Decorator{
    constructor(circle){
        this.circle = circle;
    }
    draw(){
        this.circle.draw();
        this.setRedBorder(circle);
    }
    setRedBorder(circle){
        console.log('设置红色边框')
    }
}


let circle = new Circle();
circle.draw();

let dec = new Decorator(circle);
dec.draw();

```

## 场景
- ES7 装饰器
    - 配置环境
    - 装饰类
        - demo 
        ```js 
            @testDec
            class Demo{
                //xxxx
            }

            function testDec(target){

                target.isDec = true;

                // 可以加参数
                // return function(target){
                //    target.isDec = isDec;
                //}
            }

            alert(Demo.isDec)
        ```
    - 装饰方法
- core-decorators

### 装饰器的原理
```js 
@decorator
class A{};

// 等同于

class A {}
A= decorator(A) || A

```

### 装饰类一mixin 示例
```js 

function mixins(...list){
    return function(target){
        Object.assign(target.prototype, ...list);
    }
}

const Foo = {
    foo(){
        alert('foo')
    }
}


@mixins(Foo)
class Myclass{}

let obj = new Myclass();

obj.foo();// foo
```

### 装饰方法 一例1
```js 
class Person {
    constructor(){
        this.first = 'a';
        this.last = 'b';
    }

    // 装饰方法
    @readonly
    name(){return this.a+this.b}
}


var p = new Person();

console.log(p.name());

// p.name = function （){}//  这里会报错，因为 name 是只读属性


function readonly(target, name, descriptor){
decorator.writable = false; // 关闭可写
return descriptor;
}
```

### 装饰方法 一例2

```js 
class Math{
    // 装饰方法
    @log
    add(a,b){
        return a + b;
    }
}

function log(target, name, descriptor){
    var oldValue = descriptor.value;
    descriptor.value = function(){
        console.log(name, arguments);
        return oldValue.apply(this, arguments);
    }

    return descriptor;
}
const math = new Math();
const result = math.add(2,4);//执行 add 时，会自动打印日志，因为有 @log 装饰器
console.log('result', result);
```

- core-decorators 提供常用的装饰器
```
 npm i core-decorators --save
```
```js 
import { readonly } from 'core-decorators';

class Person {
    @readonly
    name(){
        return 'zhang'
    }
}

let p = new Person();
alert(p.name())
```


## 设计原则验证
- 将现有对象和装饰器进行分离，两者独立存在
- 符合开放封闭原则